#include "resourceeditorcommands.h"

#include "../documents/data/graphicdata.h"
#include "../editors/items/swpentitygraphicitem.h"

#include <QtGui/QGraphicsItem>

using namespace core;
using namespace swp;

ChangeTypeCommand::ChangeTypeCommand(GraphicData* data,
    SwpEntityGraphicItem* previousEntity,
    SwpEntityGraphicItem* newEntity) : QUndoCommand(),
        m_shouldDeletePrevious(false),
        m_shouldDeleteNew(false),
        m_data(data),
        m_previous(previousEntity),
        m_new(newEntity),
        m_connections()
{
    setText(QObject::tr("Item type change from \"%1\" to \"%2\"").arg(
        previousEntity->name()).arg(newEntity->name()));
}

ChangeTypeCommand::~ChangeTypeCommand()
{
    if (m_shouldDeletePrevious)
    {
        m_data->unregisterForResizeNotification(m_previous);

        delete m_previous;
    }

    if (m_shouldDeleteNew)
    {
        m_data->unregisterForResizeNotification(m_new);

        delete m_new;
    }
}

void ChangeTypeCommand::undo()
{
    if (m_previous->parentDocumentData() != m_data)
    {
        m_connections = m_data->connections(m_new);

        m_data->addGraphicItem(m_previous);

        QSet<IEditorItem* > toBeNotified;

        foreach (const ConnectionData& data, m_connections)
        {
            QGraphicsItem* _connector = dynamic_cast<QGraphicsItem* >(
                    data.Connector);

            if (_connector != 0)
            {
                IEditorItem* notifee = data.From == m_new ?
                    data.To : data.From;
                toBeNotified.insert(notifee);
            }

            m_data->removeConnection(data.From, data);
            m_data->removeConnection(data.To, data);
            m_data->removeConnection(data.Connector, data);

            m_data->removeModelConnection(data);
        }

        foreach (IEditorItem* notifee, toBeNotified)
        {
            notifee->connectionsRefreshed();
        }

        m_data->removeGraphicItem(m_new, true);

        foreach (const ConnectionData& _data, m_connections)
        {
            ConnectionData data = _data;

            data.From = data.From == m_new ? m_previous : data.From;
            data.To = data.To == m_new ? m_previous : data.To;

            m_data->addConnection(data.From, data);
            m_data->addConnection(data.To, data);
            m_data->addConnection(data.Connector, data);

            m_data->addModelConnection(data);

            toBeNotified.insert(data.From);
            toBeNotified.insert(data.To);
            toBeNotified.insert(data.Connector);
        }

        foreach (IEditorItem* notifee, toBeNotified)
        {
            notifee->connectionsRefreshed();
        }
    }

    m_shouldDeleteNew = true;
    m_shouldDeletePrevious = false;
}

void ChangeTypeCommand::redo()
{
    if (m_new->parentDocumentData() != m_data)
    {
        m_connections = m_data->connections(m_previous);

        m_data->addGraphicItem(m_new);

        QSet<IEditorItem* > toBeNotified;

        foreach (const ConnectionData& data, m_connections)
        {
            QGraphicsItem* _connector = dynamic_cast<QGraphicsItem* >(
                    data.Connector);

            if (_connector != 0)
            {
                IEditorItem* notifee = data.From == m_previous ?
                    data.To : data.From;
                toBeNotified.insert(notifee);
            }

            m_data->removeConnection(data.From, data);
            m_data->removeConnection(data.To, data);
            m_data->removeConnection(data.Connector, data);

            m_data->removeModelConnection(data);
        }

        foreach (IEditorItem* notifee, toBeNotified)
        {
            notifee->connectionsRefreshed();
        }

        m_data->removeGraphicItem(m_previous, true);

        foreach (const ConnectionData& _data, m_connections)
        {
            ConnectionData data = _data;

            data.From = data.From == m_previous ? m_new : data.From;
            data.To = data.To == m_previous ? m_new : data.To;

            m_data->addConnection(data.From, data);
            m_data->addConnection(data.To, data);
            m_data->addConnection(data.Connector, data);

            m_data->addModelConnection(data);

            toBeNotified.insert(data.From);
            toBeNotified.insert(data.To);
            toBeNotified.insert(data.Connector);
        }

        foreach (IEditorItem* notifee, toBeNotified)
        {
            notifee->connectionsRefreshed();
        }
    }

    m_shouldDeleteNew = false;
    m_shouldDeletePrevious = true;
}
